package com.aeye.mbr.common.base;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ClassUtils;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * Created by chengshengru on 17-9-6.
 */
public abstract class BaseInterceptor extends HandlerInterceptorAdapter {


    private final static Logger log = LoggerFactory.getLogger(BaseInterceptor.class);

    protected abstract boolean preHandle(HttpServletRequest request, HttpServletResponse response, HandlerMethod hm)
            throws Exception;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        if (handler instanceof HandlerMethod) {
            return this.preHandle(request, response, (HandlerMethod) handler);
        }
        return super.preHandle(request, response, handler);
    }

    protected boolean isAjax(Method method) {
        return "void".equalsIgnoreCase(method.getReturnType().getCanonicalName())
                || method.getAnnotation(ResponseBody.class) != null;
    }

    protected boolean isAjax(HandlerMethod hm) {
        RestController controller = getAnnotationFromClass(hm.getBean(), RestController.class);
        if (controller != null) {
            return true;
        } else {
            return isAjax(hm.getMethod());
        }
    }


    protected void sendRawData(HttpServletResponse response, String data, boolean isClosed, String contentType) {
        if (data != null) {
            PrintWriter writer = null;
            try {
                response.setCharacterEncoding("utf-8");
                response.setContentType("text/html;charset=UTF-8");
                writer = response.getWriter();
                writer.write(data);
                writer.flush();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (writer != null && isClosed) {
                    writer.close();
                }
            }
        }
    }

    protected void sendRawData(HttpServletResponse response, String data, String contentType) {
        sendRawData(response, data, true, contentType);
    }

    protected void sendJsonData(HttpServletResponse response, String data) {
        sendRawData(response, data, "application/json;charset=UTF-8");
    }

    protected Class<?> getControllerClass(Object bean) {
        Class<?> clazz = null;
        try {
            if (bean != null) {
                String className = bean.getClass().getName();
                if (className.indexOf("$$EnhancerByCGLIB$$") > -1 || className.indexOf("$$EnhancerBySpringCGLIB$$") > -1) {  // 如果是CGLIB动态生成的类
                    className = className.substring(0, className.indexOf("$$"));
                    clazz = ClassUtils.getDefaultClassLoader().loadClass(className);
                    //clazz = ClassLoader.getSystemClassLoader().loadClass(className);
                } else {
                    clazz = bean.getClass();
                }
            }
        } catch (Exception e) {

        }
        return clazz;
    }

    protected <T extends Annotation> T getAnnotationFromClass(Object bean, Class<T> annotationClass) {
        try {
            Class<?> clazz = getControllerClass(bean);
            if (clazz != null) {
                return clazz.getAnnotation(annotationClass);
            }
        } catch (Exception e) {
            log.error(this.getClass() + ".getClassAnnotation" + e.getMessage());
        }
        return null;
    }

    protected <T extends Annotation> T getAnnotation(Object bean, Method method, Class<T> annotationClass) {
        T annotation = method.getAnnotation(annotationClass);
        if (annotation == null) {
            annotation = getAnnotationFromClass(bean, annotationClass);
        }
        return annotation;
    }

    protected <T extends Annotation> T getAnnotation(HandlerMethod hm, Class<T> annotationClass) {
        return getAnnotation(hm.getBean(), hm.getMethod(), annotationClass);
    }


    /**
     * 从Url获取微信WechatConfigId
     *
     * @return
     */
    protected String getWechatConfigId(HttpServletRequest request) {
        return getPathVariable(request, "configId");
    }


    /**
     * 获取@PathVariable参数
     *
     * @param request
     * @param key
     * @param <T>
     * @return
     */
    protected <T extends Object> T getPathVariable(HttpServletRequest request, String key) {
        Map variables = (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
        if (variables != null) {
            return (T) variables.get(key);
        }
        return null;
    }

}
